package com.css.devops.rest;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;

import org.apache.http.HttpHeaders;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.BasicCookieStore;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.css.devops.config.JenkinsProperties;
import com.css.devops.constants.DevopsConstants;
import com.css.devops.utils.JsonMapperUtils;
import com.fasterxml.jackson.databind.JsonNode;

import cn.hutool.core.util.URLUtil;
import io.swagger.annotations.Api;
import lombok.extern.slf4j.Slf4j;

/**
 * Login Jenkins and Redirect console log page 
 */
@Slf4j
@Api(tags = "Devops：登录Devops后并跳转到Job构建的日志界面")
@RestController
@RequestMapping("${devops-context}/jobLog")
public class DevopsJobLogResource {

	@Autowired
	private JenkinsProperties jenkinsProperties;
	
	/**
	 * 跳转构建日志
	 * @param jobName
	 * @param branch
	 * @param buildNumber
	 * @param response
	 */
	@GetMapping("{jobName}/{branch}/buildNumber")
	public void redirectJobLogs(@PathVariable("jobName") String jobName,@PathVariable("branch") String branch,@PathVariable("buildNumber") String buildNumber,HttpServletResponse response) {
		BasicCookieStore cookieStore = new BasicCookieStore();

        try (CloseableHttpClient httpClient = HttpClients.custom().setDefaultCookieStore(cookieStore).build()) {
        	setCrumbIssuerField4Header(httpClient, response);
        	
        	// Submit login form
        	String jenkinsLogin = String.format(DevopsConstants.JENKINS_LOGIN_URL, jenkinsProperties.getUrl());
            HttpPost postLogin = new HttpPost(jenkinsLogin);
            List<BasicNameValuePair> formParams = new ArrayList<>();
            formParams.add(new BasicNameValuePair("j_username", jenkinsProperties.getUsername()));
            formParams.add(new BasicNameValuePair("j_password", jenkinsProperties.getPassword()));
            formParams.add(new BasicNameValuePair("from", "/"));
            postLogin.setEntity(new UrlEncodedFormEntity(formParams));
            
            try (CloseableHttpResponse loginResponse = httpClient.execute(postLogin)) {
                int statusCode = loginResponse.getStatusLine().getStatusCode();
                if (statusCode == HttpStatus.OK.value() || statusCode == HttpStatus.SEE_OTHER.value()) {
                	for (org.apache.http.cookie.Cookie cookie : cookieStore.getCookies()) {
                	    Cookie servletCookie = new Cookie(cookie.getName(), cookie.getValue());
                	    servletCookie.setPath("/");
                	    servletCookie.setHttpOnly(true);
                	    servletCookie.setSecure(false);
                	    servletCookie.setDomain(URLUtil.url(jenkinsProperties.getUrl()).getHost());
                	    response.addCookie(servletCookie);
                	    
                        // Optional: Debugging
                        String cookieHeader = String.format("%s=%s; Domain=%s; Path=/; HttpOnly; SameSite=None; Secure",cookie.getName(), cookie.getValue(),URLUtil.url(jenkinsProperties.getUrl()).getHost());
                        response.addHeader("Set-Cookie", cookieHeader);
                	}
                	// Redirect build log URL for job
                	String jenkinsBuildJobLog = String.format(DevopsConstants.JENKINS_BUILD_JOB_LOG, jenkinsProperties.getUrl(),jobName,branch,buildNumber);
                	response.sendRedirect(jenkinsBuildJobLog);
                } else {
                    response.sendError(HttpStatus.UNAUTHORIZED.value(), "Login failed.");
                }
            }
        } catch (IOException e) {
        	log.error(e.getMessage(), e);
            try {
				response.sendError(HttpStatus.INTERNAL_SERVER_ERROR.value(), "Error during login process.");
			} catch (IOException e1) {
				log.error(e.getMessage(), e);
			}
        }
	}
	
	/**
	 * set crumbIssue for response headers
	 * @param httpClient
	 * @param response
	 */
	public void setCrumbIssuerField4Header(CloseableHttpClient httpClient,HttpServletResponse response) {
		try {
			String crumb_url = String.format(DevopsConstants.JENKINS_CRUMB, jenkinsProperties.getUrl());
			HttpGet httpGet = new HttpGet(crumb_url);
			httpGet.setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_ATOM_XML_VALUE);
			httpGet.setHeader(HttpHeaders.AUTHORIZATION, "Basic " + org.springframework.http.HttpHeaders.encodeBasicAuth(jenkinsProperties.getUsername(), jenkinsProperties.getPassword(), StandardCharsets.UTF_8));
			
			CloseableHttpResponse httpResponse = httpClient.execute(httpGet);
			String html = EntityUtils.toString(httpResponse.getEntity());
			JsonNode rootNode = JsonMapperUtils.getInstance().readTree(html);
			String crumb = rootNode.path("crumb").asText();
			String crumbRequestField = rootNode.path("crumbRequestField").asText();
			
			response.addHeader(crumbRequestField, crumb);
		}catch (Exception e) {
			log.error(e.getMessage(), e);
		}
	}
}
